package agentFramework.core;

import java.util.ArrayList;
import java.util.Deque;
import java.util.LinkedList;
import java.util.Queue;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

import agentFramework.action.Action;
import agentFramework.core.Message;
import agentFramework.core.MessageDispatcher;
import agentFramework.core.env.Environment;
import agentFramework.strategy.Strategy;


public abstract class Core extends Thread
{
	public static final int			SIM_WAIT = 1;
	public static final int			SIM_RUNNING = 0;
	public static final int			id = -1;
	
	private MessageDispatcher		messageDispatcher;  // the object that delivers the messages
	
	public  Environment				environment;   // the reference to the environment
	public 	Deque<Message>			messageQueue;  // the message queue
	public  Lock					lock;          // a lock object using in accessing the message queue
	
	/* used for GUI communication */
	public  Lock					stepLock;
	public 	Lock					epochLock;
	public  int						stepStatus;

	// constructor
	public Core(Environment env)
	{
		this.messageQueue = new LinkedList<Message>();
		this.environment = env;
		this.messageDispatcher = env.getMessageDispatcher();
		this.lock = new ReentrantLock();
		this.stepLock = new ReentrantLock();
		this.epochLock = new ReentrantLock();
	}
	
	
	// thread's main loop
	public void run()
	{
		behavior();
	}
	

	// adds a message in the agent's message queue
	// this is practically used only by the MessageDispatcher object
	public final void addMessage(Message msg)
	{
		lock.lock();
		messageQueue.addLast(msg);
		lock.unlock();
	}
	
	
	// this function passes the message to the MessageDispatcher object
	// to deliver it using the message header info (type, destination etc.)
	public final void sendMesage(Message msg)
	{
		messageDispatcher.addMessage(msg);
	}
	
	public void getStepLock ()
	{
		stepLock.lock();
	}
	
	public void releaseStepLock ()
	{
		stepLock.unlock();
	}
	
	public void getEpochLock ()
	{
		epochLock.lock();
	}
	
	public void releaseEpochLock ()
	{
		epochLock.unlock();
	}
	
	public int getStepStatus ()
	{
		return stepStatus;
	}
	

	// TO BE IMPLEMENTED
	// this function handles the given message taking a proper action 
	public abstract void handleMessage(Message msg);
	
	
	// TO BE IMPLEMENTED
	// this function describes the way the core works, how and when 
	// the messages are processed etc.
	// this function needs to active the agents, send synchronize messages etc.
	public abstract void behavior();
}